package com.googlecode.particlesys.objects;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.util.concurrent.atomic.AtomicBoolean;

public class Particle extends Position {

	private final AtomicBoolean expired = new AtomicBoolean(false);
	private EParticleShape shape;
	private double velocityX;
	private double velocityY;
	private double speed;
	private int life = 1024;
	private int maxLife = 1024;
	protected Color color = Color.WHITE;
	private Image image;
	private int weight;
	private double angle;
	private double originalSpeed = Long.MAX_VALUE;
	private Seeker seeker;
	
	public Particle(Color color, EParticleShape shape, int width, int height){
		super(width, height);
		this.color = color;
		this.shape = shape;
	}
	
	public Particle(Color color, int width, int height){
		this(color, EParticleShape.BOX, width, height);
	}
	
	public void draw(Graphics g, Component component){
		g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), calculateAlpha()));
		
		switch(shape){
		case BOX:
			g.fillRect(x, y, width, height);
			break;
			
		case SPHERE:
			g.fillOval(x, y, width, height);
			break;
			
		case IMAGE:
			if(image != null){
				Graphics2D g2d = (Graphics2D) g;
				Composite original = g2d.getComposite();
				
				AlphaComposite myAlpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float)calculateAlpha()/255f);
				g2d.setComposite(myAlpha);
				
				g.drawImage(image, x, y, width, height, component);
				
				g2d.setComposite(original);
			}
			break;
		}
	}
	
	public void update(int gravity){
		if(life-- <= 0){
			expired.set(true);
			return;
		}
		
		speed -= gravity/32D;
		
		if(speed <= Math.sqrt(originalSpeed)){
			//System.out.println("apply gravity: "+speed+":"+originalSpeed);
			y += gravity;
		}
		
		if(seeker != null){
			setAngle(seeker.calculateAngle(x, y));
		} else {
			setAngle(this.angle);
		}
		
		x += (int) velocityX;
		y += (int) velocityY;
	}
	
	public boolean hasCollidedWith(Position other){
		return true;
	}
	
	private int calculateAlpha(){
		return 255*life/maxLife;
	}
	
	public void setAngle(double angle){
		this.angle = angle;
		velocityX = speed * Math.cos(angle/180D*Math.PI);
		velocityY = speed * Math.sin((360D-angle)/180D*Math.PI);
	}
	
	@Override
	public String toString(){
		return "Position: <"+x+", "+y+">, Velocity: <"+velocityX+", "+velocityY+">";
	}
	
	public double getVelocityX(){
		return velocityX;
	}
	
	public void setVelocityX(double velocityX){
		this.velocityX = velocityX;
	}
	
	public double getVelocityY(){
		return velocityY;
	}
	
	public void setVelocityY(double velocityY){
		this.velocityY = velocityY;
	}
	
	public double getSpeed(){
		return speed;
	}
	
	public void setSpeed(double speed){
		this.speed = speed;
		
		if(originalSpeed == Long.MAX_VALUE){
			originalSpeed = speed;
		}
	}

	public boolean isExpired(){
		return expired.get();
	}

	public void setLife(int life){
		this.maxLife = life;
		this.life = life;
	}

	public int getLife(){
		return life;
	}

	public Color getColor(){
		return color;
	}

	public void setColor(Color color){
		this.color = color;
	}

	public void setImage(Image image){
		this.image = image;
	}

	public void setWeight(int weight){
		this.weight = weight;
	}

	public int getWeight(){
		return weight;
	}

	public void setSeeker(Seeker seeker){
		this.seeker = seeker;
	}

	public Seeker getSeeker(){
		return seeker;
	}
}